#include "dbreg.h"
#include "ti_stdint.h"
#include "alu.h"
#include "guidebug.h"
#include "print.h"
#include "expandpane.h"
#include "dbvalue.h"


extern HINSTANCE g_hInst;

extern HFONT hfontSegoe, hfontLucida, hfontLucidaBold;

#define DBREG_ORGX	12
#define DBREG_ORGY	0

struct db_reg {
	unsigned int offset;
	char name[8];
};
	
static const struct db_reg reg_offset[] = {
	coff(af,"af"), coff(afp,"af'"),
	coff(bc,"bc"), coff(bcp,"bc'"),
	coff(de,"de"), coff(dep,"de'"),
	coff(hl,"hl"), coff(hlp,"hl'"),
	coff(ix,"ix"), coff(sp,"sp"),
	coff(iy,"iy"), coff(pc,"pc"), 
	coff(i,"i"), coff(imode,"im"), coff(r,"r")};
	//coff(halt,"hlt"), coff(iff1,"iff1"),coff(iff2,"iff2")};
	
static RECT val_locs[NumElm(reg_offset)];
static int kRegRow, kRegAddr;

void ValueDraw(HDC hdc, RECT *dr, int i) {
	char szRegVal[16];

	dr->right = dr->left + kRegAddr;
	sprintf(szRegVal, "%s", reg_offset[i].name);
	SelectObject(hdc, hfontLucida);
	SetTextColor(hdc, DBCOLOR_HILIGHT);
	DrawText(hdc, szRegVal, -1, dr, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
	
	SetTextColor(hdc, RGB(0,0,0));
	dr->left = dr->right;
	dr->right += kRegAddr;
	SelectObject(hdc, hfontLucida);
	
	if (i < REG16_ROWS * REG16_COLS) {	
		sprintf(szRegVal, "%04X", reg16(reg_offset[i].offset));
		DrawText(hdc, szRegVal, -1, dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
	} else {
		sprintf(szRegVal, "%02X", reg8(reg_offset[i].offset));
		DrawText(hdc, szRegVal, -1, dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
	}
	val_locs[i] = *dr;
	
}

static TEXTMETRIC tm;
static HWND hwndVal = NULL;
static int vi;

void HandleEditMessages(HWND hwnd, WPARAM wParam, LPARAM lParam) {
	switch (HIWORD(wParam)) {
		case EN_CHANGE:
		case 256:
		case EN_UPDATE:
		case EN_MAXTEXT:
			break;
		
		case EN_KILLFOCUS:
			if (GetFocus() == hwnd) break;
		case EN_SUBMIT:
			
		default:
		if (vi != -1) {
			if (vi < REG16_ROWS*REG16_COLS) {
				ValueSubmit(hwndVal,
					((unsigned char*) (&calcs[gslot].cpu)) + reg_offset[vi].offset,
					2);
			} else {
				ValueSubmit(hwndVal,
					((unsigned char*) (&calcs[gslot].cpu)) + reg_offset[vi].offset,
					1);
				
			}
			SendMessage(GetParent(hwnd), WM_USER, DB_UPDATE, 0);
		}					
		hwndVal = NULL;
		return;
	}
	return;
}

void ClearEditField(HWND hwnd) {

	if (hwndVal) {
		SendMessage(hwnd, WM_COMMAND, EN_SUBMIT<<16, (LPARAM) hwndVal);
	}
	
}

void CreateEditField(HWND hwnd, POINT p) {
	
	if (hwndVal) {
		SendMessage(hwnd, WM_COMMAND, EN_SUBMIT<<16, (LPARAM) hwndVal);
	}
	
	unsigned int i;
	for (i = 0; i < NumElm(reg_offset); i++) {
		if (PtInRect(&val_locs[i], p)) {
			vi = i;
			break;
		}
	}
	
	if (i == NumElm(reg_offset)) {
		vi = -1;
		return;
	}
	RECT r;
	GetClientRect(hwnd, &r);
	
	hwndVal = NULL;
	char rval[8];
	int edit_width = 4;
	if (vi < REG16_ROWS*REG16_COLS) {
		sprintf(rval, "%04X", reg16(reg_offset[vi].offset));
		edit_width = 4;
	} else {
		sprintf(rval, "%02X", reg8(reg_offset[vi].offset));
		edit_width = 2;
	}
		
	
	RECT rrc;
	GetWindowRect(hwnd, &rrc);
	
	hwndVal = 
	CreateWindow("EDIT", rval,
		WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_MULTILINE,
		val_locs[vi].left-2,
		val_locs[vi].top,
		(edit_width*kRegAddr/4)+4,
		kRegRow,
		hwnd, 
		0, g_hInst, NULL);
		
	SubclassEdit(hwndVal, edit_width);
}


LRESULT CALLBACK DBRegProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
	
	switch (Message) {
	case WM_CREATE:
	{
		struct {char *name; void *data; size_t size;} reg[] =
		{
				{"af", &calcs[gslot].cpu.af, 2}, {"af'", &calcs[gslot].cpu.afp, 2},
				{"bc", &calcs[gslot].cpu.bc, 2}, {"bc'", &calcs[gslot].cpu.bcp, 2},
				{"de", &calcs[gslot].cpu.de, 2}, {"de'", &calcs[gslot].cpu.dep, 2},
				{"hl", &calcs[gslot].cpu.hl, 2}, {"hl'", &calcs[gslot].cpu.hlp, 2},
				{"ix", &calcs[gslot].cpu.ix, 2}, {"sp",  &calcs[gslot].cpu.sp, 2},
				{"iy", &calcs[gslot].cpu.iy, 2}, {"pc",  &calcs[gslot].cpu.pc, 2},
		};
			
		// Create all of the value fields
		int i;
		for (i = 0; i < NumElm(reg); i++) {
			HWND hwndValue = CreateValueField(hwnd, reg[i].name, reg[i].data, reg[i].size);
			SetWindowPos(hwndValue, NULL, (i % 2) * kRegAddr*3, kRegRow * (i/2), 0, 0, SWP_NOZORDER | SWP_NOSIZE);
			SendMessage(hwndValue, WM_SIZE, 0, 0);
		}
		return 0;
	}
	case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc;
	
		hdc = BeginPaint(hwnd, &ps);
	
		RECT rc;
		GetClientRect(hwnd, &rc);
		
		FillRect(hdc, &rc, GetStockObject(WHITE_BRUSH));
		
		EndPaint(hwnd, &ps);
		return 0;
	}
	case WM_SIZE: 
	{
		SetWindowPos(hwnd, NULL, 0, 0, kRegAddr*6, kRegRow*8, SWP_NOMOVE | SWP_NOZORDER);
		return 0;
	}
	default:
		return DefWindowProc(hwnd, Message, wParam, lParam);
	}
	
}

LRESULT CALLBACK DBFlagProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
	static HWND chk_z, chk_c, chk_s, chk_pv, chk_hc, chk_n,
								chk_iff1, chk_iff2, chk_halt;
	#define FLAGS_TOP 0
	
	switch (Message) {
		case WM_CREATE: {
			
			HFONT hfontFlags = hfontSegoe;
			
			chk_z =
			CreateWindow(
				"BUTTON",
				"z",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX, // | BS_LEFTTEXT,
				0, FLAGS_TOP, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_Z, g_hInst, NULL);
			SendMessage(chk_z, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
	
			chk_c =
			CreateWindow(
				"BUTTON",
				"c",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX, // | BS_LEFTTEXT,
				2*kRegAddr, FLAGS_TOP, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_C, g_hInst, NULL);
			SendMessage(chk_c, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
	
			chk_s =
			CreateWindow(
				"BUTTON",
				"s",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX, // | BS_LEFTTEXT,
				4*kRegAddr, FLAGS_TOP, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_S, g_hInst, NULL);
			SendMessage(chk_s, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
	
			chk_pv =
			CreateWindow(
				"BUTTON",
				"p/v",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX, // | BS_LEFTTEXT,
				0, FLAGS_TOP + kRegRow, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_PV, g_hInst, NULL);	
			SendMessage(chk_pv, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
	
			chk_hc =
			CreateWindow(
				"BUTTON",
				"hc",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX, // | BS_LEFTTEXT,
				2*kRegAddr, FLAGS_TOP + kRegRow, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_HC, g_hInst, NULL);	
			SendMessage(chk_hc, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
				
			chk_n =
			CreateWindow(
				"BUTTON",
				"n",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX, // | BS_LEFTTEXT,
				4*kRegAddr, FLAGS_TOP + kRegRow, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_N, g_hInst, NULL);
			SendMessage(chk_n, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
			return 0;
		}
		case WM_CTLCOLORSTATIC:
		case WM_CTLCOLORBTN:
		{
			return GetStockObject(WHITE_BRUSH);
		}
		
		case WM_MOVE:
			return 0;
			
		case WM_COMMAND:
		{
			switch (HIWORD(wParam)) {
				case BN_CLICKED:
					switch (LOWORD(wParam)) {
						case REG_CHK_Z:
							calcs[gslot].cpu.f ^= ZERO_MASK;
							break;
						case REG_CHK_C:
							calcs[gslot].cpu.f ^= CARRY_MASK;
							break;
						case REG_CHK_S:
							calcs[gslot].cpu.f ^= SIGN_MASK;
							break;
						case REG_CHK_PV:
							calcs[gslot].cpu.f ^= PV_MASK;
							break;
						case REG_CHK_HC:
							calcs[gslot].cpu.f ^= HC_MASK;
							break;	
						case REG_CHK_N:
							calcs[gslot].cpu.f ^= N_MASK;
							break;
					}
					SendMessage(hwnd, WM_USER, DB_UPDATE, 0);
					SendMessage(GetParent(hwnd), WM_USER, DB_UPDATE, 0);
					return 0;
			}
			
			return 0;
		}
		case WM_PAINT: {
			PAINTSTRUCT ps;
			HDC hdc;
			hdc = BeginPaint(hwnd, &ps);
			
			RECT rc;
			GetClientRect(hwnd, &rc);
			
			FillRect(hdc, &rc, GetStockObject(WHITE_BRUSH));
			
			EndPaint(hwnd, &ps);
			return 0;
		}
		case WM_SIZE: {
			SetWindowPos(hwnd, NULL, 0, 0, kRegAddr*6, kRegRow*4, SWP_NOMOVE | SWP_NOZORDER);
			return 0;
		}
		case WM_USER: {
			switch (wParam) {
			case DB_UPDATE: {
				SendMessage(chk_z, BM_SETCHECK, 
				(calcs[gslot].cpu.f & ZERO_MASK) ? BST_CHECKED : BST_UNCHECKED, 0);
				SendMessage(chk_c, BM_SETCHECK, 
				(calcs[gslot].cpu.f & CARRY_MASK) ? BST_CHECKED : BST_UNCHECKED, 0);
				SendMessage(chk_s, BM_SETCHECK, 
				(calcs[gslot].cpu.f & SIGN_MASK) ? BST_CHECKED : BST_UNCHECKED, 0);
				SendMessage(chk_pv, BM_SETCHECK, 
				(calcs[gslot].cpu.f & PV_MASK) ? BST_CHECKED : BST_UNCHECKED, 0);
				SendMessage(chk_hc, BM_SETCHECK, 
				(calcs[gslot].cpu.f & HC_MASK) ? BST_CHECKED : BST_UNCHECKED, 0);					
				SendMessage(chk_n, BM_SETCHECK, 
				(calcs[gslot].cpu.f & N_MASK) ? BST_CHECKED : BST_UNCHECKED, 0);
				break;
			}
			}
			return 0;
		}
		default:
			return DefWindowProc(hwnd, Message, wParam, lParam);
	}
}

					
LRESULT CALLBACK RegProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
	static HWND chk_z, chk_c, chk_s, chk_pv, chk_hc, chk_n,
								chk_iff1, chk_iff2, chk_halt;
	static HWND hwndExp;

	switch (Message) {
		case WM_CREATE:
		{
			HDC hdc = GetDC(hwnd);

			SelectObject(hdc, hfontLucida);
			GetTextMetrics(hdc, &tm);
			kRegRow = tm.tmHeight + tm.tmHeight/3;
			kRegAddr = tm.tmAveCharWidth*4;
			
			RECT r;
			GetClientRect(hwnd, &r);

#define REGISTERS_TOP 2*kRegRow
#define VECTORS_TOP (12*kRegRow+kRegRow/2)
			
			WNDCLASSEX wcx;
			ZeroMemory(&wcx, sizeof(wcx));
			
			wcx.cbSize = sizeof(wcx);
			wcx.style = CS_DBLCLKS;
			wcx.lpszClassName = "WabbitRegDisp";
			wcx.lpfnWndProc = DBRegProc;
			wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
			RegisterClassEx(&wcx);
			
			wcx.lpszClassName = "WabbitFlagDisp";
			wcx.lpfnWndProc = DBFlagProc;
			RegisterClassEx(&wcx);
			
			HWND hwndContent;
			
			hwndContent = 
				CreateWindow(
						"WabbitRegDisp", 
						"Registers", 
						WS_CHILD | WS_CLIPCHILDREN, 
						0, 0, 1, 1, 
						hwnd, 
						(HMENU) 1, g_hInst, NULL);
			
			hwndExp = CreateExpandPane(hwnd, "Registers", hwndContent);
			
			hwndContent = 
				CreateWindow(
						"WabbitFlagDisp", 
						"Flags", 
						WS_CHILD | WS_CLIPCHILDREN, 
						0, 0, 1, 1, 
						hwnd, 
						(HMENU) 1, g_hInst, NULL);
			CreateExpandPane(hwnd, "Flags", hwndContent);
			
			CreateExpandPane(hwnd, "CPU Status", NULL);
			CreateExpandPane(hwnd, "Interrupts", NULL);
			CreateExpandPane(hwnd, "Display", NULL);
			CreateExpandPane(hwnd, "Linking", NULL);
			HFONT hfontFlags = hfontSegoe;
			
			/*
			chk_z =
			CreateWindow(
				"BUTTON",
				"z",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX, // | BS_LEFTTEXT,
				kRegAddr, FLAGS_TOP, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_Z, g_hInst, NULL);
			SendMessage(chk_z, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
			
			chk_c =
			CreateWindow(
				"BUTTON",
				"c",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX, // | BS_LEFTTEXT,
				3*kRegAddr, FLAGS_TOP, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_C, g_hInst, NULL);
			SendMessage(chk_c, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
			
			chk_s =
			CreateWindow(
				"BUTTON",
				"s",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX, // | BS_LEFTTEXT,
				5*kRegAddr, FLAGS_TOP, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_S, g_hInst, NULL);
			SendMessage(chk_s, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
			
			chk_pv =
			CreateWindow(
				"BUTTON",
				"p/v",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX, // | BS_LEFTTEXT,
				kRegAddr, FLAGS_TOP + kRegRow, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_PV, g_hInst, NULL);	
			SendMessage(chk_pv, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);

			chk_hc =
			CreateWindow(
				"BUTTON",
				"hc",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX, // | BS_LEFTTEXT,
				3*kRegAddr, FLAGS_TOP + kRegRow, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_HC, g_hInst, NULL);	
			SendMessage(chk_hc, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
				
			chk_n =
			CreateWindow(
				"BUTTON",
				"n",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX, // | BS_LEFTTEXT,
				5*kRegAddr, FLAGS_TOP + kRegRow, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_N, g_hInst, NULL);
			SendMessage(chk_n, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
			
			chk_halt =
			CreateWindow(
				"BUTTON",
				"halt",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
				kRegAddr, VECTORS_TOP, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_HALT, g_hInst, NULL);		
			SendMessage(chk_halt, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
	
			chk_iff1 =
			CreateWindow(
				"BUTTON",
				"iff1",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
				3*kRegAddr,VECTORS_TOP, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_IFF1, g_hInst, NULL);	
			SendMessage(chk_iff1, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
				
			chk_iff2 =
			CreateWindow(
				"BUTTON",
				"iff2",
				WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
				5*kRegAddr, VECTORS_TOP, 3*kRegAddr/2, kRegRow,
				hwnd, (HMENU) REG_CHK_IFF2, g_hInst, NULL);	
			SendMessage(chk_iff2, WM_SETFONT, (WPARAM) hfontFlags, (LPARAM) TRUE);
			*/
			ReleaseDC(hwnd, hdc);
			return 0;
		}
		
		case WM_SIZE:
		{
			//RECT rc;
			//GetClientRect(hwnd, &rc);
			//SetWindowPos(hwndExp, NULL, 0, 0, 180, kRegAddr*2, SWP_NOZORDER);
			ArrangeExpandPanes();
			InvalidateRect(hwnd, NULL, FALSE);
			UpdateWindow(hwnd);
			return 0;
		}
		case WM_CTLCOLORSTATIC:
		case WM_CTLCOLORBTN:
		{
			SetBkMode(wParam, TRANSPARENT);
			SetTextColor(wParam, RGB(0, 255, 0));
			return GetStockObject(WHITE_BRUSH);
		}
		case WM_COMMAND:
			switch (HIWORD(wParam)) {
				case EN_CHANGE:
				case 256:
				case EN_UPDATE:
				case EN_MAXTEXT:
					break;
				
				case EN_KILLFOCUS:
					if (GetFocus() == hwnd) break;
				case EN_SUBMIT:
					
				default:
				if (vi != -1) {
					if (vi < REG16_ROWS*REG16_COLS) {
						ValueSubmit(hwndVal,
							((unsigned char*) (&calcs[gslot].cpu)) + reg_offset[vi].offset,
							2);
					} else {
						ValueSubmit(hwndVal,
							((unsigned char*) (&calcs[gslot].cpu)) + reg_offset[vi].offset,
							1);
						
					}
					SendMessage(GetParent(hwnd), WM_USER, DB_UPDATE, 0);
				}					
				hwndVal = NULL;
				switch (HIWORD(wParam)) {
				case BN_CLICKED:
				{
					switch (LOWORD(wParam)) {
						case REG_CHK_Z:
							calcs[gslot].cpu.f ^= ZERO_MASK;
							break;
						case REG_CHK_C:
							calcs[gslot].cpu.f ^= CARRY_MASK;
							break;
						case REG_CHK_S:
							calcs[gslot].cpu.f ^= SIGN_MASK;
							break;
						case REG_CHK_PV:
							calcs[gslot].cpu.f ^= PV_MASK;
							break;
						case REG_CHK_HC:
							calcs[gslot].cpu.f ^= HC_MASK;
							break;	
						case REG_CHK_N:
							calcs[gslot].cpu.f ^= N_MASK;
							break;
						case REG_CHK_HALT:
							calcs[gslot].cpu.halt ^= 1;
							break;
						case REG_CHK_IFF1:
							calcs[gslot].cpu.iff1 ^= 1;
							break;
						case REG_CHK_IFF2:
							calcs[gslot].cpu.iff2 ^= 1;
							break;										
						default:
						{
							unsigned short swap;
							int ri = LOWORD(wParam) - REG_SWAPID;
							if (ri < 4) {
								swap = reg16(reg_offset[ri*2].offset);
								reg16(reg_offset[ri*2].offset) = reg16(reg_offset[ri*2+1].offset);
								reg16(reg_offset[ri*2+1].offset) = swap;
							}
						}
					}
					
					SendMessage(GetParent(hwnd), WM_USER, DB_UPDATE, 0);
					break;
				}
				}
			}
			return 0;
		case WM_PAINT:
		{
			PAINTSTRUCT ps;
			HDC hdc, hdcDest;

			hdcDest = BeginPaint(hwnd, &ps);
			RECT r, dr;
			GetClientRect(hwnd, &r);
			FillRect(hdcDest, &r, GetStockObject(WHITE_BRUSH));
			DrawEdge(hdcDest, &r,EDGE_ETCHED, BF_LEFT);
			EndPaint(hwnd, &ps);
			return 0;
			
			
			char szRegVal[16];
			
			GetClientRect(hwnd, &r);

			hdc = CreateCompatibleDC(hdcDest);
			HBITMAP hbm = CreateCompatibleBitmap(hdcDest, r.right, r.bottom);
			SelectObject(hdc, hbm);
			
			SetBkMode(hdc, TRANSPARENT);
			
			FillRect(hdc, &r, GetStockObject(WHITE_BRUSH));
			
			
			DrawHeader(hdc, "Registers", kRegRow/2);
			
			r.left = kRegRow;
			int i, j, ind = 0;
			for (	i = 0, r.top = REG_TOP, r.bottom = r.top + kRegRow;
					i < REG16_ROWS;
					i++, OffsetRect(&r, 0, kRegRow)) {
						
				CopyRect(&dr, &r);
				ValueDraw(hdc, &dr, ind++);

				OffsetRect(&dr, 2*kRegAddr, 0);
				ValueDraw(hdc, &dr, ind++);
			}
			
			DrawHeader(hdc,  "Flags", r.top + kRegRow/2);
			OffsetRect(&r, 0, 5*kRegRow + kRegRow/2);
			
			DrawHeader(hdc, "Interrupts", r.top + kRegRow/2);
			/* Draw checkboxes here */
			OffsetRect(&r, 0, 2*kRegRow);
			
			for (i = 0; i < REG8_ROWS; i++, OffsetRect(&r, 0, kRegRow)) {
				
				CopyRect(&dr, &r);
				for (	j = 0; 
						j < REG8_COLS; 
						j++, 
						dr.left += 2*kRegAddr) {
					RECT cpyr = dr;
					ValueDraw(hdc, &cpyr, ind++);
				}
			}
			
			
			OffsetRect(&r, 0, kRegRow);
			
			CopyRect(&dr, &r);
			dr.right = 2*kRegAddr;
			SelectObject(hdc, hfontLucidaBold);
			DrawText(hdc, "(hl) ", -1, &dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
			dr.left += kRegAddr;
			int val = mem_read(calcs[gslot].cpu.mem_c, calcs[gslot].cpu.hl);
			sprintf(szRegVal, "%02X", val);
			SelectObject(hdc, hfontLucida);
			DrawText(hdc, szRegVal, -1, &dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
			
			OffsetRect(&dr,2*kRegAddr,0);
			dr.left -= kRegAddr;
			SelectObject(hdc, GetStockObject(SYSTEM_FONT));
			DrawText(hdc, "(ix) ", -1, &dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
			val = mem_read(calcs[gslot].cpu.mem_c, calcs[gslot].cpu.ix);
			sprintf(szRegVal, "%02X", val);
			dr.left += kRegAddr;
			SelectObject(hdc, GetStockObject(ANSI_FIXED_FONT));
			DrawText(hdc, szRegVal, -1, &dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
			
			OffsetRect(&dr,2*kRegAddr,0);	
			dr.left -= kRegAddr;
			SelectObject(hdc, GetStockObject(SYSTEM_FONT));
			DrawText(hdc, "(iy) ", -1, &dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
			val = mem_read(calcs[gslot].cpu.mem_c, calcs[gslot].cpu.iy);
			sprintf(szRegVal, "%02X", val);
			dr.left += kRegAddr;
			SelectObject(hdc, GetStockObject(ANSI_FIXED_FONT));
			DrawText(hdc, szRegVal, -1, &dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
			
			OffsetRect(&r, 0, 3*kRegRow/2);
			
			CopyRect(&dr, &r);
			dr.right = 8*kRegAddr;
			SelectObject(hdc, GetStockObject(SYSTEM_FONT));
			DrawText(hdc, "Int. Status:", -1, &dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
			val = calcs[gslot].cpu.pio.stdint->intactive;
			sprintf(szRegVal, "%02X", val);
			dr.left += 3*kRegAddr;
			SelectObject(hdc, GetStockObject(ANSI_FIXED_FONT));
			DrawText(hdc, szRegVal, -1, &dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
			
			OffsetRect(&r, 0, 3*kRegRow/2);
			
			CopyRect(&dr, &r);
			dr.right = 8*kRegAddr;
			SelectObject(hdc, GetStockObject(SYSTEM_FONT));
			DrawText(hdc, "Next Timer1:", -1, &dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
			double ntimer = tc_elapsed(&calcs[gslot].timer_c) - calcs[gslot].cpu.pio.stdint->lastchk1;
			ntimer *= 1000;
			sprintf(szRegVal, "%0.4lf ms", ntimer);
			dr.left += 3*kRegAddr;
			SelectObject(hdc, GetStockObject(ANSI_FIXED_FONT));
			DrawText(hdc, szRegVal, -1, &dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
			
			OffsetRect(&r, 0, kRegRow);
			
			CopyRect(&dr, &r);
			dr.right = 8*kRegAddr;
			SelectObject(hdc, GetStockObject(SYSTEM_FONT));
			DrawText(hdc, "Timer1 Dur.:", -1, &dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
			ntimer = calcs[gslot].cpu.pio.stdint->timermax1;
			ntimer *= 1000;
			sprintf(szRegVal, "%0.4lf ms", ntimer);
			dr.left += 3*kRegAddr;
			SelectObject(hdc, GetStockObject(ANSI_FIXED_FONT));
			DrawText(hdc, szRegVal, -1, &dr, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
			
			
			GetClientRect(hwnd, &r);
			BitBlt(hdcDest, DBREG_ORGX, DBREG_ORGY, r.right - DBREG_ORGX*2, r.bottom, hdc, 0, 0, SRCCOPY);
			
			r.right = DBREG_ORGX;
			FillRect(hdcDest, &r, GetStockObject(WHITE_BRUSH)); //GetSysColorBrush(COLOR_BTNFACE));
			r.top = 0;
			DrawEdge(hdcDest, &r,EDGE_ETCHED, BF_LEFT);
			
			GetClientRect(hwnd, &r);
			r.left = r.right - DBREG_ORGX;
			FillRect(hdcDest, &r, GetStockObject(WHITE_BRUSH));

			EndPaint(hwnd, &ps);
			
			DeleteObject(hbm);	
			DeleteDC(hdc);
		
			return 0;
		}
		case WM_USER:
			switch (wParam) {
				//case PANE_UPDATE:
				case DB_UPDATE:
				{
					SendMessage(chk_z, BM_SETCHECK, 
					(calcs[gslot].cpu.f & ZERO_MASK) ? BST_CHECKED : BST_UNCHECKED, 0);
					SendMessage(chk_c, BM_SETCHECK, 
					(calcs[gslot].cpu.f & CARRY_MASK) ? BST_CHECKED : BST_UNCHECKED, 0);
					SendMessage(chk_s, BM_SETCHECK, 
					(calcs[gslot].cpu.f & SIGN_MASK) ? BST_CHECKED : BST_UNCHECKED, 0);
					SendMessage(chk_pv, BM_SETCHECK, 
					(calcs[gslot].cpu.f & PV_MASK) ? BST_CHECKED : BST_UNCHECKED, 0);
					SendMessage(chk_hc, BM_SETCHECK, 
					(calcs[gslot].cpu.f & HC_MASK) ? BST_CHECKED : BST_UNCHECKED, 0);					
					SendMessage(chk_n, BM_SETCHECK, 
					(calcs[gslot].cpu.f & N_MASK) ? BST_CHECKED : BST_UNCHECKED, 0);
					
					SendMessage(chk_halt, BM_SETCHECK, 
					(calcs[gslot].cpu.halt) ? BST_CHECKED : BST_UNCHECKED, 0);		
					SendMessage(chk_iff1, BM_SETCHECK, 
					(calcs[gslot].cpu.iff1) ? BST_CHECKED : BST_UNCHECKED, 0);
					SendMessage(chk_iff2, BM_SETCHECK, 
					(calcs[gslot].cpu.iff2) ? BST_CHECKED : BST_UNCHECKED, 0);										

					InvalidateRect(hwnd, NULL, TRUE);
					UpdateWindow(hwnd);
						 
					return 0;
				}
			}
			return 0;
		case WM_LBUTTONDBLCLK:
		case WM_LBUTTONDOWN:
		{
			return 0;
		}
		default:
			return DefWindowProc(hwnd, Message, wParam, lParam);
	}
	return 0;
}
